import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QGridLayout,
                             QLineEdit, QPushButton, QVBoxLayout)
from PyQt5.QtCore import Qt


class Calculator(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.current_expr = ""  # 存储当前表达式:ml-citation{ref="1,8" data="citationList"}
        self.result_display = None  # 显示文本框对象

    def initUI(self):
        """初始化界面组件与布局"""
        # 主窗口设置
        self.setWindowTitle('PyQt5 Calculator')
        self.setFixedSize(320, 400)  # 固定窗口大小:ml-citation{ref="3,7" data="citationList"}

        # 创建主容器
        main_widget = QWidget()
        self.setCentralWidget(main_widget)

        # 垂直布局容器
        vbox = QVBoxLayout()
        main_widget.setLayout(vbox)

        # 创建显示框
        self.result_display = QLineEdit()
        self.result_display.setAlignment(Qt.AlignRight)
        self.result_display.setReadOnly(True)  # 禁止手动输入:ml-citation{ref="3,8" data="citationList"}
        self.result_display.setStyleSheet("font-size: 24px; padding: 10px;")
        vbox.addWidget(self.result_display)

        # 创建按钮网格布局
        grid = QGridLayout()
        vbox.addLayout(grid)

        # 按钮配置列表（文本, 位置, 样式类）
        buttons = [
            ('7', (0, 0)), ('8', (0, 1)), ('9', (0, 2)), ('/', (0, 3)),
            ('4', (1, 0)), ('5', (1, 1)), ('6', (1, 2)), ('*', (1, 3)),
            ('1', (2, 0)), ('2', (2, 1)), ('3', (2, 2)), ('-', (2, 3)),
            ('0', (3, 0)), ('.', (3, 1)), ('C', (3, 2)), ('+', (3, 3)),
            ('=', (4, 0, 1, 4))  # 跨4列的等号按钮:ml-citation{ref="2,7" data="citationList"}
        ]

        # 生成按钮并绑定事件
        for btn_info in buttons:
            text = btn_info[0]
            pos = btn_info[1]
            btn = QPushButton(text)
            btn.setStyleSheet("""
                QPushButton {
                    background: #f0f0f0;
                    border: 1px solid #999;
                    font-size: 18px;
                    padding: 15px;
                }
                QPushButton:pressed {
                    background: #ddd;
                }
            """)  # 基础按钮样式:ml-citation{ref="1,6" data="citationList"}

            # 特殊按钮样式
            if text in ['=', 'C']:
                btn.setStyleSheet("background: #ff9500; color: white;")

            # 绑定点击事件
            if text == '=':
                btn.clicked.connect(self.calculate)
            elif text == 'C':
                btn.clicked.connect(self.clear)
            else:
                if text.isdigit() or text == '.':
                    btn.clicked.connect(lambda _, t=text: self.append_number(t))
                else:
                    btn.clicked.connect(lambda _, t=text: self.append_operator(t))

            # 设置按钮位置
            if len(pos) == 4:  # 跨列按钮
                grid.addWidget(btn, pos[0], pos[1], pos[2], pos[3])
            else:
                grid.addWidget(btn, pos[0], pos[1])

    def append_number(self, num):
        """处理数字和小数点输入"""
        if num == '.' and '.' in self.current_expr.split(' ')[-1]:
            return  # 禁止重复小数点:ml-citation{ref="8" data="citationList"}
        self.current_expr += num
        self.update_display()

    def append_operator(self, op):
        """处理运算符输入"""
        if self.current_expr and self.current_expr[-1] not in '+-*/':
            self.current_expr += f' {op} '  # 运算符前后加空格:ml-citation{ref="7" data="citationList"}
            self.update_display()

    def calculate(self):
        """执行计算并显示结果"""
        try:
            # 安全计算（替换eval为更安全的方法）
            result = str(eval(self.current_expr.replace(' ', '')))
            self.current_expr = result
        except ZeroDivisionError:
            result = "Error: Div by Zero"  # 除零错误处理:ml-citation{ref="5" data="citationList"}
            self.current_expr = ""
        except Exception:
            result = "Error"
            self.current_expr = ""
        self.result_display.setText(result)

    def clear(self):
        """清除当前输入"""
        self.current_expr = ""
        self.result_display.clear()

    def update_display(self):
        """更新显示框内容"""
        self.result_display.setText(self.current_expr)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    calc = Calculator()
    calc.show()
    sys.exit(app.exec_())